#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int Wins[]={448,56,7,292,146,73,273,84};
int Lazis[]={1,2,4,8,16,32,64,128,256};
int intBoard[]={0,0,0};
/*
 *index0:all
 *index1:red
 *index2:black
 */
int mp[]={28,26,24,16,14,12,4,2,0};
unsigned char charBoard[]={56,179,55,179,54,10,/*0-5,0,2,4*/
                           32,197,32,197,32,10,
                           53,179,52,179,51,10,/*12-17,12,14,16*/
                           32,197,32,197,32,10,
                           50,179,49,179,48,10/*24-29,24,26,28*/
                           ,0
                          };
int Layers,tmpLayers;
int minLayer(int mnbrd,int rdbrd,int blckbrd,int &mv);
int maxLayer(int mnbrd,int rdbrd,int blckbrd,int &mv);
int Layer();
//Function
int isEnd(int x){
  return x==511;
}
int isWin(int x){
  for(int i=0;i<8;i++)
    if((x&Wins[i])==Wins[i])
      return Wins[i];
  return 0;
}
int isOccupy(int x,int board){
  return (board&Lazis[x])==Lazis[x];
}
int lazi(int x,int *board){
  return *board=(*board)|Lazis[x];
}
int isLayerEnd(){
  return !(tmpLayers--);
}
int reintLayers(){
  return Layers=0;
}
//AI 
int maxLayer(int mnbrd,int rdbrd,int blckbrd,int &mv){
  int tmpls=tmpLayers;
  if(isEnd(mnbrd)||isLayerEnd())return 0;
  int value=-1;
  for(int i=0;i<9&&value<1;i++){
    if(isOccupy(i,mnbrd))continue;
    if(isWin(rdbrd|Lazis[i]))return mv=i,value=1;
    int tmp=-1;
    int blckvl=minLayer(mnbrd|Lazis[i],rdbrd|Lazis[i],blckbrd,tmp);
    tmpLayers=tmpls;
    value=value>blckvl?value:(mv=i,blckvl);
  }
  return value;
}
int minLayer(int mnbrd,int rdbrd,int blckbrd,int &mv){
  int tmpls=tmpLayers;
  if(isEnd(mnbrd)||isLayerEnd())return 0;
  int value=1,bestmove=-1;
  for(int i=0;i<9&&value>-1;i++){
    if(isOccupy(i,mnbrd))continue;
    if(isWin(blckbrd|Lazis[i])){
      return mv=i,value=-1;
    }
    int tmp=-1;
    int rdvl=maxLayer(mnbrd|Lazis[i],rdbrd,blckbrd|Lazis[i],tmp);
    tmpLayers=tmpls;
    value=value>rdvl?(mv=i,rdvl):value;
  }
  return value;
}
int Layer(){
  int aimove=-1;
  maxLayer(intBoard[0],intBoard[1],intBoard[2],aimove);
  return aimove;
}
//UI
int humanhandle=-1;
char dots[2]={'X','H'};
void printBoard(){
  printf("%s",charBoard);
}
char *getWho(){
  return (char*)(dots[0]=='X'?"you":(humanhandle==0?"A":"B"));
}
int inPos(){
  int i;
  printf("input the pos %s choose\n:",getWho());
  scanf("%d",&i);
  return i;
}
void putBoard(int x,char c){
  charBoard[mp[x]]=c;
}
void reintBoard(){
  for(int i=0;i<9;i++)
    charBoard[mp[i]]=48+i;
  intBoard[0]=intBoard[1]=intBoard[2]=0;
}
int aiRound(){
  int aimove=Layer();
  //ai落子
  lazi(aimove,&intBoard[0]);
  lazi(aimove,&intBoard[1]);
  putBoard(aimove,'A');
  system("cls");
  printBoard();
  if(isWin(intBoard[1])){
    printf("ai Win!\n");
    return 1;
  }
  if(isEnd(intBoard[0])){
    printf("Gameover,draw!\n");
    return 1;
  }
  printf("ai choose %d\n",aimove);
  return 0;
}
int humRound(){
  int i;
  while((i=inPos())<0||i>8||isOccupy(i,intBoard[0]))
    printf("illegal pos\n");
  //人类落子
  lazi(i,&intBoard[0]);
  lazi(i,&intBoard[1+humanhandle]);
  putBoard(i,dots[humanhandle]);
  system("cls");
  printBoard();
  if(isWin(intBoard[1+humanhandle])){
    printf("%s choose %d\n",getWho(),i);
    printf("%s win!\n",getWho());
    return 1;
  }
  printf("%s choose %d\n",getWho(),i);
  if(isEnd(intBoard[0])){
    printf("Gameover,draw!\n");
    return 1;
  }
  return 0;
}
int haRound(){
  system("cls");
  while(!(Layers>0&&Layers<10)){
    printf("Please choose the difficulty(input 1 to 9)\n:");
    scanf("%d",&Layers);
  }
  int flag=-1;
  while(!(flag==0||flag==1)){
    printf("Who is the first?AI:0,HUM:1.(input 0 or 1)\n:");
    scanf("%d",&flag);
  }
  int (*rounds[2])();
  rounds[flag]=aiRound;
  rounds[!flag]=humRound;
  system("cls");
  printBoard();
  while(1){
    tmpLayers=Layers;
    if(rounds[0]())break;
    if(rounds[1]())break;
  }
  printf("input q to quit or other key to restart\n");
  getchar();
  return getchar();
}
int hhRound(){
  dots[0]='A';
  dots[1]='B';
  system("cls");
  printBoard();
  while(1){
    if(humRound())break;
    humanhandle=!humanhandle;
  }
  printf("input q to quit or other key to restart\n");
  getchar();
  return getchar();
}
int main(){
  int (*vs)();
  SetConsoleOutputCP(437);//更换代码页以显示制表符
  while(!(humanhandle==0||humanhandle==1)){
    printf("Choose the way of fighting,human vs human:0,human vs ai:1.(input 0 or 1)\n:");
    scanf("%d",&humanhandle);
  }
  if(humanhandle==1)
    vs=haRound;
  else
    vs=hhRound;
  while(1){
    reintBoard();
    reintLayers();
    if(vs()=='q')break;
  }
  return 0;
}
